import * as vscode from 'vscode';
import { getConfig } from './configManager';
import neo4j from 'neo4j-driver';
import type { Neo4jRecord, Neo4jInteger } from 'neo4j-driver';

export async function getTestableMethods(): Promise<any[]> {
  const config = getConfig();
  const driver = neo4j.driver(config.neo4j.serverUrl, neo4j.auth.basic(config.neo4j.serverUser, config.neo4j.serverPassword));
  const session = driver.session();

  const query = `
    MATCH (m:Method)
    WHERE m.modifiers CONTAINS "public" AND NOT m.modifiers CONTAINS "abstract" AND m.type = "METHOD"
    RETURN id(m) AS node_id, m.signature AS signature, m.absolute_path AS absolutePath, m.start_line AS startLine, m.end_line AS endLine
  `;

  try {
    const result = await session.run(query);
    const methods = result.records.map((record: Neo4jRecord) => ({
      nodeId: record.get<Neo4jInteger>('node_id')?.toNumber() ?? 0,
      signature: record.get<string>('signature'),
      absolutePath: record.get<string>('absolutePath'),
      startLine: record.get<Neo4jInteger>('startLine')?.toNumber(),
      endLine: record.get<Neo4jInteger>('endLine')?.toNumber(),
    }));

    console.log('Fetched testable methods:', methods); // 调试日志
    return methods;
  } catch (error) {
    if (error instanceof Error) {
      vscode.window.showErrorMessage(`Failed to fetch testable methods: ${error.message}`);
    } else {
      vscode.window.showErrorMessage('Failed to fetch testable methods: Unknown error');
    }
    return [];
  } finally {
    await session.close();
    await driver.close();
  }
}

export async function getMethodCallGraph(nodeId: number): Promise<string> {
  const config = getConfig();
  const driver = neo4j.driver(config.neo4j.serverUrl, neo4j.auth.basic(config.neo4j.serverUser, config.neo4j.serverPassword));
  const session = driver.session();

  const query = `
    MATCH (m:Method)-[r]-(n)
    WHERE id(m) = $nodeId
    RETURN m, r, n
  `;

  try {
    const result = await session.run(query, { nodeId });
    return result.records.length > 0 ? `MATCH (m)-[r]-(n) WHERE id(m) = ${nodeId} RETURN m, r, n` : '';
  } catch (error) {
    if (error instanceof Error) {
      vscode.window.showErrorMessage(`Failed to fetch method call graph: ${error.message}`);
    } else {
      vscode.window.showErrorMessage('Failed to fetch method call graph: Unknown error');
    }
    return '';
  } finally {
    await session.close();
    await driver.close();
  }
}

export async function getMethodDetails(nodeId: number): Promise<any> {
  const config = getConfig();
  const driver = neo4j.driver(config.neo4j.serverUrl, neo4j.auth.basic(config.neo4j.serverUser, config.neo4j.serverPassword));
  const session = driver.session();

  const query = `
    MATCH (m:Method)
    WHERE id(m) = $nodeId
    RETURN m.signature AS signature, m.absolute_path AS absolutePath, m.start_line AS startLine, m.end_line AS endLine
  `;

  try {
    const result = await session.run(query, { nodeId });
    if (result.records.length > 0) {
      const record = result.records[0] as Neo4jRecord;
      return {
        signature: record.get<string>('signature'),
        absolutePath: record.get<string>('absolutePath'),
        startLine: record.get<Neo4jInteger>('startLine')?.toNumber(), // 使用 toNumber() 转换
        endLine: record.get<Neo4jInteger>('endLine')?.toNumber(), // 使用 toNumber() 转换
      };
    } else {
      vscode.window.showErrorMessage(`No method found with ID: ${nodeId}`);
      return null;
    }
  } catch (error) {
    if (error instanceof Error) {
      vscode.window.showErrorMessage(`Failed to fetch method details: ${error.message}`);
    } else {
      vscode.window.showErrorMessage('Failed to fetch method details: Unknown error');
    }
    return null;
  } finally {
    await session.close();
    await driver.close();
  }
}

export async function hasDirectTestClazz(nodeId: number): Promise<boolean> {
  const config = getConfig();
  const driver = neo4j.driver(config.neo4j.serverUrl, neo4j.auth.basic(config.neo4j.serverUser, config.neo4j.serverPassword));
  const session = driver.session();

  const query = `
    MATCH (m:Method)-[]-(t:Method)
    WHERE id(m) = $nodeId AND t.type = "TEST_METHOD"
    RETURN count(t) > 0 AS hasTest
  `;

  try {
    const result = await session.run(query, { nodeId });
    if (result.records.length > 0) {
      return Boolean(result.records[0].get<boolean>('hasTest'));
    }
    return false;
  } catch (error) {
    if (error instanceof Error) {
      vscode.window.showErrorMessage(`Failed to check test class: ${error.message}`);
    } else {
      vscode.window.showErrorMessage('Failed to check test class: Unknown error');
    }
    return false;
  } finally {
    await session.close();
    await driver.close();
  }
}
